package cn.itcast.nems.studentrecord.service.impl;

import cn.itcast.nems.common.service.BizNumberService;
import cn.itcast.nems.order.api.OrderApi;
import cn.itcast.nems.studentrecord.constant.ReferenceTypeEnum;
import cn.itcast.nems.studentrecord.converter.StudentRecordReceivableConverter;
import cn.itcast.nems.studentrecord.converter.StudentRecordReferenceConverter;
import cn.itcast.nems.studentrecord.dao.entity.StudentRecord;
import cn.itcast.nems.studentrecord.dao.entity.StudentRecordTransaction;
import cn.itcast.nems.studentrecord.dto.change.StudentRecordChangeCheckOriginDTO;
import cn.itcast.nems.studentrecord.dto.change.StudentRecordJournalDTO;
import cn.itcast.nems.studentrecord.dto.change.StudentRecordJournalDropoutDTO;
import cn.itcast.nems.studentrecord.dto.change.StudentRecordTransactionChangeCheckDTO;
import cn.itcast.nems.studentrecord.dto.studentrecord.StudentRecordFundFlowDTO;
import cn.itcast.nems.studentrecord.dto.studentrecord.StudentRecordReceivableCreateDTO;
import cn.itcast.nems.studentrecord.dto.studentrecord.StudentRecordReferenceDTO;
import cn.itcast.nems.studentrecord.enumeration.FundFlowPaymentTypeEnum;
import cn.itcast.nems.studentrecord.service.StudentRecordDropoutService;
import cn.itcast.nems.studentrecord.service.settlement.SettlementCalculatorDropout;
import cn.itcast.nems.studentrecord.service.settlement.SettlementResult;
import cn.itcast.nems.studentrecord.service.studentrecord.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author liyong
 * create: 2023-12-07 21:04:59
 **/
@Service
public class StudentRecordDropoutServiceImpl extends StudentRecordChangeServiceImpl implements StudentRecordDropoutService {
    private final StudentRecordFundFlowService studentRecordFundFlowService;
    private final BizNumberService bizNumberService;

    public StudentRecordDropoutServiceImpl(StudentRecordTransactionService studentRecordTransactionService,
                                           StudentRecordService studentRecordService,
                                           StudentRecordCreateService studentRecordCreateService,
                                           StudentRecordMessageService studentRecordMessageService,
                                           StudentRecordReceivableService studentRecordReceivableService,
                                           StudentRecordFundFlowService studentRecordFundFlowService,
                                           BizNumberService bizNumberService,
                                           OrderApi orderApi) {
        super(studentRecordService,
                studentRecordCreateService,
                studentRecordTransactionService,
                studentRecordMessageService,
                studentRecordReceivableService,
                orderApi);
        this.studentRecordFundFlowService = studentRecordFundFlowService;
        this.bizNumberService = bizNumberService;
    }

    @Transactional
    @Override
    public void dropout(StudentRecordJournalDropoutDTO studentRecordJournalDropout) {
        final Integer refundAmount = 0; //TODO 未来调整退学退费逻辑 studentRecordJournalDropout.getAmount();
        SettlementCalculatorDropout calculator = new SettlementCalculatorDropout(studentRecordJournalDropout.createSettlementResult());
        logger.info("处理退学: {}", studentRecordJournalDropout);
        final SettlementResult settlementResult = super.studentRecordService.studentRecordSettlement(
                studentRecordJournalDropout.getStudentRecordId(),
                studentRecordJournalDropout.getClazzOutDate().toLocalDate(),
                calculator);
        
        logger.info("{}退学结算结果: {}", studentRecordJournalDropout.getStudentRecordId(), settlementResult);
        StudentRecordJournalDTO joutnalDTO = convertJournalDTO(studentRecordJournalDropout);
        StudentRecord sr = this.studentRecordService.getById(studentRecordJournalDropout.getStudentRecordId());
        StudentRecordReferenceDTO dto = StudentRecordReferenceConverter.origin(sr, joutnalDTO);
        
        logger.info("创建退学流转记录，学籍ID: '{}' {}", sr.getId(), dto);
        super.createStudentRecordTransaction(dto, settlementResult, StudentRecordTransaction.TYPE_OUT);
        this.addStudentRecordFundFlow(studentRecordJournalDropout, refundAmount);
        
        final int receivableChangeAmount = calculator.getReceivableChangeAmount();
        logger.info("{}退学流转应收明细变更{}", sr.getId(), receivableChangeAmount);
        if (receivableChangeAmount != 0) {
            final StudentRecordReceivableCreateDTO recordReceivableDTO = StudentRecordReceivableConverter.createDTO(studentRecordJournalDropout,
                    sr.getId(),
                    receivableChangeAmount);
            logger.info("退学学籍创建应收信息{}", recordReceivableDTO);
            super.addStudentRecordReceivable(recordReceivableDTO);
        }
        
        super.studentRecordService.unlock(studentRecordJournalDropout.getStudentRecordId());
    }

    @Override
    StudentRecordChangeChecker createStudentRecordChangeChecker(StudentRecordChangeCheckOriginDTO studentRecordOrigin, List<StudentRecordTransactionChangeCheckDTO> transactions) {
        return new StudentRecordChangeDropoutChecker(studentRecordOrigin, transactions);
    }

    // 学籍添加退费流水
    private void addStudentRecordFundFlow(StudentRecordJournalDropoutDTO journalDropout, Integer refundAmout) {
        if (refundAmout != null && refundAmout > 0) {
            StudentRecordFundFlowDTO fundFlow = new StudentRecordFundFlowDTO();
            fundFlow.setStudentRecordId(journalDropout.getStudentRecordId());
            fundFlow.setClazzId(journalDropout.getClazzId());
            fundFlow.setClazzName(journalDropout.getClazzName());
            fundFlow.setReferenceType(ReferenceTypeEnum.REFUND);
            fundFlow.setBizDate(journalDropout.getClazzOutDate());
            fundFlow.setReferenceId(journalDropout.getRefundJournalId());
            fundFlow.setReferenceLineId(journalDropout.getRefundJournalLineId());
            fundFlow.setPaymentType(FundFlowPaymentTypeEnum.REFUND);
            // FIXME paymentNo应该保存对应的退费凭单号
//            fundFlow.setPaymentNo(this.bizNumberService.next(BizNumberTypeEnum.ORDER_REFUND));
            fundFlow.setAmount(-refundAmout);
            fundFlow.setCharge(0);
            fundFlow.setPaymentMethodCode("");
            fundFlow.setPaymentMethodName("");
            fundFlow.setPaymentAccountCode("");
            fundFlow.setPaymentAccountName("");
            fundFlow.setRemark(ReferenceTypeEnum.DROPOUT.getName());
            fundFlow.setUpdateStudentRecord(Boolean.FALSE);
            this.studentRecordFundFlowService.create(fundFlow);
        }
    }

    private StudentRecordJournalDTO convertJournalDTO(StudentRecordJournalDropoutDTO studentRecordJournalDropout) {
        StudentRecordJournalDTO journal = new StudentRecordJournalDTO();
        journal.setJournalType(ReferenceTypeEnum.DROPOUT);
        journal.setJournalId(studentRecordJournalDropout.getJournalId());
        journal.setJournalLineId(studentRecordJournalDropout.getJournalLineId());
        journal.setOriginClazzId(studentRecordJournalDropout.getClazzId());
        journal.setOriginClazzName(studentRecordJournalDropout.getClazzName());
        journal.setOriginClazzOutDate(studentRecordJournalDropout.getClazzOutDate().toLocalDate());
        journal.setOriginClazzSettlementAmount(studentRecordJournalDropout.getClazzSettlementAmount());
        journal.setOriginClazzSettlementDays(studentRecordJournalDropout.getClazzSettlementDays());
        return journal;
    }
}
